'''
TwoPints.py

Class for TwoPints Object
Two Pints is the computer "player"
'''
import random
from copy import deepcopy


class TwoPints:
    def __init__(self):
        pass
    
	def makeMove(self):
		pass
	
    def selectPiece(self,game):
        # for the opening move select a random piece
        if len(game.availablePieces) == 16:
            start_piece = random.randint(0,15)
            game.selectPiece(start_piece)
        pass
    
    def placePiece(self,game):
        pass
	
	# Alpha-beta pruning stuff:

	def getNextStateAlphabeta(self,game,lookahead):
		def max_value(self,state,alpha,beta,depth):
			# check if we've reached the depth or if we're at a final state ( where the selectedPiece = None )
			if depth > lookahead or not state[1]:
				return self.stateEval(state)
			v = float('-inf') # -infinity
			for s in self.getSuccessors(state):
				v = max(v, min_value(s,alpha,beta,depth+1))
				if v >= beta:
					return v
				alpha = max(alpha,v)
			return v
			
		def min_value(self,state,alpha,beta,depth):
			# check if we've reached the depth or if we're at a final state ( where the selectedPiece = None )
			if depth > lookahead or not state[1]:
				return self.stateEval(state)
			v = float('inf') # infinity
			for s in self.getSuccessors(state):
				v = min(v, max_value(s,alpha,beta,depth+1))
				if v <= alpha:
					return v
				beta = min(beta,v)
			return v
		neg_infinity = float('-inf')
		infinity = float('inf')
		state = self.argmax(self.getSuccessors(state), lambda s:min_value(s,neg_infinity,infinity,0))
		return state
		
	def getSuccessors(self,state):
		''' 
		state = a QuartoGame
		starting with naive approach
		need to work on accounting for symmetries
		'''
        successors = []
        
        x = 0
        while x < 4:
            y = 0
            while y < 4:
                if not state.board.spots[x][y]:
                    new_state = deepcopy(state)
                    new_state.placePiece(x,y)
                    
                    for p in new_state.availablePieces:
                        new_state.selectPiece(p)
                        successors.append(new_state)
                        
        return successors
				
	def stateEval(self):
		pass
	
	def argmin(self,seq, fn):
		'''Return an element with lowest fn(seq[i]) score; tie goes to first one.
		>>> argmin(['one', 'to', 'three'], len)
		'to'
		'''
		best = seq[0]; best_score = fn(best)
		for x in seq:
			x_score = fn(x)
			if x_score < best_score:
				best, best_score = x, x_score
		return best
		
	def argmax(self,seq, fn):
		'''Return an element with highest fn(seq[i]) score; tie goes to first one.
		>>> argmax(['one', 'to', 'three'], len)
		'three'
		'''
		return self.argmin(seq, lambda x: -fn(x))
        
    def int2bin(self, n, count=4):
        return "".join([str((n >> y) & 1) for y in range(count - 1, -1, -1)])
